﻿using AutoMapper;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Admin.Domain;
using Windows.Admin.Infrastructure.EFCore;
using Windows.Admin.Infrastructure.EFCore.Extensions;
using Windows.Infrastructure.Share.Extensions;
using Windows.Infrastructure.Share.Security;
using Windows.Infrastructure.EFCore.Share.Extensions;
using Windows.Infrastructure.Share.CustomException;
using Windows.Infrastructure.Share.Tools;

namespace Windows.Admin.Service
{
    public class PrivilegeService: IPrivilegeService
    {
        private readonly IMapper _mapper;
        private readonly ICurrentUser _currentUser;
        private readonly AdminDbContext _db;
        public PrivilegeService(IMapper mapper, AdminDbContext db, ICurrentUser currentUser)
        {
            _mapper = mapper;
            _db = db;
            _currentUser = currentUser;
        }
        /// <summary>
        /// 获取当前用户的许可证列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<string>> GetCurrentUserLicenses()
        {
            List<string>? licenses = null;

            //如果是管理员
            if (_currentUser.IsAdmin)
            {
                licenses = await _db.App.Where(x => x.License != null && x.License != "").Select(x => x.License!).ToListAsync();
            }
            else
            {
                //获取用户
                var user =  await _db.User.Include(x => x.Employees).ThenInclude(x => x.Organization_Employees).ThenInclude(x => x.Organization).ThenInclude(x => x!.Role_Organizations).Include(x => x.Employees).ThenInclude(x=>x.Post_Employees).ThenInclude(x=>x.Post).ThenInclude(x=>x!.Role_Posts).Include(x => x.Role_Users).FindByIdAsync(_currentUser.Id);
                //获取用户的角色Ids
                var userRoleIds = user!.Role_Users.Select(s => s.RoleId).ToArray();
                var employee = user.Employees!.FirstOrDefault()!;
                //获取员工的组织机构
                var organizationIds = employee.Organization_Employees.Select(s => s.OrganizationId).ToArray();
                organizationIds ??= Array.Empty<long>();
                //获取员工的组织机构的角色Ids
                var organizationRoleIds = employee.Organization_Employees.SelectMany(s => s.Organization!.Role_Organizations).Select(s => s.RoleId).ToArray();
                var postIds = employee.Post_Employees.Select(s => s.PostId).ToArray();
                var postRoleIds = employee.Post_Employees.SelectMany(s => s.Post!.Role_Posts).Select(s => s.RoleId).ToArray();
                postRoleIds ??= Array.Empty<long>();
                //获取资源列表
                var appIds = await _db.Privilege.GetByMasterValues(_currentUser.Id, organizationIds, postIds, userRoleIds, organizationRoleIds, postRoleIds).Select(s => s.AccessValue).Distinct().ToListAsync();
                //获取功能许可证列表
                licenses = await _db.App.Where(x => appIds.Contains(x.Id) && x.License != null && x.License != "").Select(s => s.License!).ToListAsync();
            }
            return licenses;
        }
        /// <summary>
        /// 获取当前用户的Privileges
        /// </summary>
        /// <returns></returns>
        public async Task<List<Privilege>?> GetCurrentUserPrivileges()
        {
            //获取用户
            var user = await _db.User.Include(x => x.Employees).ThenInclude(x => x.Organization_Employees).ThenInclude(x => x.Organization).ThenInclude(x => x!.Role_Organizations).Include(x => x.Employees).ThenInclude(x => x.Post_Employees).ThenInclude(x => x.Post).ThenInclude(x => x!.Role_Posts).Include(x => x.Role_Users).FindByIdAsync(_currentUser.Id);
            if (user != null)
            {
                //获取用户的角色Ids
                var userRoleIds = user!.Role_Users.Select(s => s.RoleId).ToArray();
                var organizationIds = Array.Empty<long>();
                var organizationRoleIds = Array.Empty<long>();
                var postIds = Array.Empty<long>();
                var postRoleIds = Array.Empty<long>();
                var employee = user.Employees!.FirstOrDefault();
                if (employee != null) 
                {
                    //获取员工的组织机构
                    organizationIds = employee.Organization_Employees.Select(s => s.OrganizationId).ToArray();
                    //获取员工的组织机构的角色Ids
                    organizationRoleIds = employee.Organization_Employees.SelectMany(s => s.Organization!.Role_Organizations).Select(s => s.RoleId).ToArray();
                    postIds = employee.Post_Employees.Select(s => s.PostId).ToArray();
                    postRoleIds = employee.Post_Employees.SelectMany(s => s.Post!.Role_Posts).Select(s => s.RoleId).ToArray();
                }
                //获取资源列表
                var privileges = await _db.Privilege.GetByMasterValues(_currentUser.Id, organizationIds, postIds, userRoleIds, organizationRoleIds, postRoleIds).ToListAsync();
                return privileges;
            }
            return null;
        }
        /// <summary>
        /// 获取权限
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<List<PrivilegeResponse>> GetPrivileges(PrivilegeRequest request)
        {
            MasterEnum master = request.Master.GetEnum<MasterEnum>();
            //获取权限列表
            List<Privilege> privileges = await _db.Privilege.Get(master, request.Id).ToListAsync();
            return _mapper.Map<List<PrivilegeResponse>>(privileges);
        }
        /// <summary>
        /// 设置权限
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task SetPrivileges(SetPrivilegeRequest request)
        {
            if (request.Id == ConfigurationUtils.GetSection("AdminRoleId").ToInt())
                throw new ApiException($"超级管理员不需设置权限!");

            MasterEnum master = request.Master.GetEnum<MasterEnum>();
            List<Privilege> privileges = await _db.Privilege.Where(x => x.Master == master.ToString() && x.MasterValue == request.Id).ToListAsync();
            _db.Privilege.RemoveRange(privileges);
            if (request.AppIds != null)
            {
                foreach (var appId in request.AppIds)
                {
                    Privilege model = new(master, request.Id, AccessEnum.App, appId);
                    await _db.Privilege.AddAsync(model);
                }
            }
            if (request.ResourceIds != null)
            {
                foreach (var operateId in request.ResourceIds)
                {
                    Privilege model = new(master, request.Id, AccessEnum.Resource, operateId);
                    await _db.Privilege.AddAsync(model);
                }
            }
            await _db.SaveChangesAsync();
        }
    }
}
